#include <iostream>
#include <vector>
#include "Thread.hpp"
#include "LockGuard.hpp"
using namespace std;
using namespace ThreadModule;

const int num = 4; // 线程数量

class ThreadData
{
public:
    ThreadData(int &tickets, const string &name, pthread_mutex_t &mutex)
        : _tickets(tickets), _name(name), _total(0), _mutex(mutex)
    {
    }
    ~ThreadData()
    {
    }

public:
    int &_tickets;           // 全局票数---所有的线程，最后都会引用同一个全局的g_tickets
    string _name;            // 名称
    int _total;              // 抢到的票数
    pthread_mutex_t &_mutex; // 锁
};

int g_tickets = 10000; // 票数---共享资源,没有做保护,导致数据不一致
// 因为没有对g_tickets全局变量访问时做保护,导致造成了数据不一致问题,即对全局变量g_tickets的访问修改不是原子的
// // 定义一个全局锁
// pthread_mutex_t mutext = PTHREAD_MUTEX_INITIALIZER; // 初始化锁
// // 抢票逻辑
// void route(ThreadData *td)
// {
//     while (true)
//     {
//         // 如果有票就抢
//         // 加锁
//         // pthread_mutex_lock(&mutext);
//         pthread_mutex_lock(&td->_mutex);
//         // 只有td中的_tickets变量属于全局共享资源，所以只需要对访问_tickets变量的代码(临界区)进行保护即可
//         if (td->_tickets > 0)
//         {
//             // 一直持续抢票
//             usleep(1000);
//             cout << "thread-name:" << td->_name << ",get tickets:" << td->_tickets << endl;
//             td->_tickets--;
//             // 解锁
//             pthread_mutex_unlock(&td->_mutex);
//             td->_total++;
//         }
//         else
//         {
//             // 解锁
//             pthread_mutex_unlock(&td->_mutex);
//             // 直到抢不到就不抢了
//             break;
//         }
//     }
// }
// 抢票逻辑
void route(ThreadData *td)
{
    while (true)
    {
        LockGuard guard(&td->_mutex);
        // guard锁在构造时加锁,析构释放时自动解锁,利用类的属性。
        // 此锁称为RAII风格的加锁和解锁
        if (td->_tickets > 0)
        {
            usleep(1000);
            cout << "thread-name:" << td->_name << ",get tickets:" << td->_tickets << endl;
            td->_tickets--;

            td->_total++;
        }
        else
        {
            break;
        }
    }
}

int main()
{
    // 使用局部锁
    pthread_mutex_t mutex;
    // 初始化局部锁
    pthread_mutex_init(&mutex, nullptr);
    cout << "main &g_tickets:" << &g_tickets << endl;
    // 创建一批线程
    vector<Thread<ThreadData *>> threads;
    vector<ThreadData *> datas;
    for (int i = 0; i < num; i++)
    {
        string name = "thread-" + to_string(i + 1);
        ThreadData *td = new ThreadData(g_tickets, name, mutex);
        threads.emplace_back(route, td, name);
        datas.emplace_back(td);
    }

    // 启动一批线程
    for (auto &thread : threads)
    {
        thread.Start();
    }
    // 等待回收一批线程
    for (auto thread : threads)
    {
        thread.join();
        // cout << "wait thread success!!! thread_name:" << thread.name() << endl;
    }
    // 输出数据信息
    for (auto &data : datas)
    {
        cout << data->_name << ":" << data->_total << endl;
        delete data;
    }
    // 销毁锁
    pthread_mutex_destroy(&mutex);
    return 0;
}

// #include <iostream>
// using namespace std;
// #include "Thread.hpp"
// #include <vector>
// using namespace ThreadModule;

// void print(int &cnt)
// {
//     while (cnt)
//     {
//         cout << "I am self Thread,cnt:" << cnt << endl;
//         cnt--;
//         sleep(1);
//     }
// }
// const int num = 10;
// int main()
// {
//     // 创建一批线程
//     vector<Thread<int>> threads;
//     for (int i = 0; i < num; i++)
//     {
//         string name = "thread-" + to_string(i + 1);
//         threads.emplace_back(print, 10, name);
//     }

//     // 启动一批线程
//     for (auto &thread : threads)
//     {
//         thread.Start();
//     }
//     // 等待回收一批线程
//     for (auto &thread : threads)
//     {
//         thread.join();
//         cout << "wait thread success!!! thread_name:" << thread.name() << endl;
//     }
//     // // 定义线程
//     // Thread<int> t1(print, 10);
//     // // 启动线程
//     // t1.Start();
//     // // 等待回收
//     // t1.join();

//     return 0;
// }

// #include <iostream>
// using namespace std;
// #include <pthread.h>
// #include <string>
// #include <cstdio>
// #include <vector>
// #include <sys/types.h>
// #include <unistd.h>
// const int pthreadnums = 5;

// void *pthreadrun(void *arg)
// {
//     const char *name = (char *)arg;
//     // while (true)
//     //{
//     sleep(1);
//     cout << "I am " << name << endl;
//     //}
//     // 释放线程名空间(堆上)
//     delete[] name;
//     return nullptr;
// }

// int main()
// {
//     // 创建多线程
//     vector<pthread_t> threads;
//     for (int i = 0; i < pthreadnums; i++)
//     {
//         pthread_t tid;
//         // 每个线程名称都在堆上为其开辟空间
//         char *pthreadname = new char[64];
//         snprintf(pthreadname, 64, "pthread-%d", i + 1);
//         pthread_create(&tid, nullptr, pthreadrun, pthreadname);
//         threads.push_back(tid);
//         sleep(1);
//     }

//     // 等待回收线程
//     for (auto &tid : threads)
//     {
//         pthread_join(tid, nullptr);
//         sleep(1);
//     }
//     return 0;
// }

// void *threadrun(void *arg)
// {
//     int cnt = 5;
//     char *name = (char *)arg;
//     while (cnt)
//     {
//         cout << name << "线程:" << cnt << " pid:" << getpid()
//              << " 新线程id" << pthread_self() << endl;
//         sleep(1);
//         // 3秒之后，此线程自主退出
//         if (cnt == 3)
//         {
//             pthread_exit(nullptr);
//         }
//         cnt--;
//     }
//     return nullptr;
// }
// int main()
// {
//     // 创建线程
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadrun, (char *)"new pthread");
//     sleep(3);
//     // 取消线程
//     // pthread_cancel(tid);
//     // 回收线程
//     void *ret = nullptr;
//     pthread_join(tid, &ret);
//     cout << "rid:" << ret << endl;
//     return 0;
// }

// string Tohex(pthread_t tid)
// {
//     char id[64];
//     snprintf(id, sizeof(id), "0x%lx", tid);
//     return id;
// }

// void *threadrun(void *arg)
// {
//     int cnt = 5;
//     char* name=(char*)arg;
//     while (cnt)
//     {
//         cout << name <<"线程:" << cnt << " pid:" << getpid() << " 新线程id" << Tohex(pthread_self()) << endl;
//         sleep(1);
//         cnt--;
//     }
//     return nullptr;
// }

// int g_val = 10;

// void *threadrun(void *arg)
// {
//     char *name = (char *)arg;
//     int cnt = 5;
//     while (cnt)
//     {
//         cout << "pthread name:" << name;
//         cout << "g_val:" << g_val << endl;
//         g_val++;
//         cnt--;
//         sleep(1);
//     }
//     return nullptr;
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadrun, (char *)"new_pthread");
//     int cnt = 10;
//     while (cnt)
//     {
//         cout << "main pthread," << "g_val:" << g_val << endl;
//         cnt--;
//         sleep(1);
//     }
//     return 0;
// }

// int main()
// {
//     // 创建线程
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadrun, nullptr);
//     sleep(6);
//     // 等待线程
//     pthread_join(tid, nullptr);
//     sleep(3);
//     // 主线程退出
//     cout << "主线程退出" << endl;
//     return 0;
// }

// int main()
// {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadrun, nullptr);
//     int cnt = 10;
//     while (cnt)
//     {
//         cout << "主线程:" << cnt << " pid:" << getpid() << " 主线程id" << Tohex(pthread_self()) << endl;
//         sleep(1);
//         cnt--;
//     }
//     return 0;
// }

// void *start_routine(void *p)
// {
//     while (true)
//     {
//         cout << "start_routine执行流,pid:" << getpid() << endl;
//         sleep(1);
//     }
// }
// int main()
// {
//     pthread_t tcb;
//     pthread_create(&tcb, nullptr, start_routine, nullptr);
//     while (true)
//     {
//         cout << "main执行流,pid:" << getpid() << endl;
//         sleep(1);
//     }
//     return 0;
// }